# coding: utf8
"""
Module Description:跨服数值型物品
Date: 2020/6/2
Anchor:Peng Ming Yuan
"""
from common.service_config import get_server_id, get_activity_id, get_action_id
from pyshare.const.enums.activity import ActivityType
from pyshare.const.enums.chat import Channel
from pyshare.dal.gameconfig.query import getProfile
from pyshare.dal.repository_impl import CrossSeasonRoleRepository, CrossSeasonScoreRepository, \
    RoleRepository, CrossSeasonServerRepository, CrossSeasonActivityRepository
from pyshare.distributed.cross_lock_define import CrossSeasonLock
from pyshare.framework.distribute.mutex import CAMutex
from pyshare.redis_cache.share.season_challenge_cache import season_challenge_cache
from pyshare.utils.game_log.game_log_define import CrossSeasonScoreLog, CrossSeasonDanExpLog
from pyshare.utils.season_rank_utils import season_rank_utils
from pyshare.utils.season_utils import get_season_base_info,\
    update_season_user_stage_score, send_system_msg, get_group_of_season_stage
from pyshare.bll.utils.share.share_role_information import ShareRoleInformation
from pyshare.utils.time_utils import getCT


class CrossSeasonScoreGoods(object):
    """
    九州之巅积分物品
    在跨服使用时注意切换上下文
    kwargs 必传 道具类型item_type(int), item_id(int),增加数量count（int）,
    activity_id(可选，有的上下文是没有activity_id，需要依靠外部传入)
    """
    def add_award(self, rid, log_param, **kwargs):
        count = kwargs.get("count", 0) if kwargs.get("count", 0) else self.count
        season_id, stage_id, _ = get_season_base_info(need_award_time=False)
        # 没有赛季不加积分
        if not season_id:
            self.is_return = False
            return
        #  activity_id(可选，有的上下文是没有activity_id，需要依靠外部传入)
        activity_id = kwargs.get("activity_id", '')
        server_id = get_server_id()
        group_id = get_group_of_season_stage(season_id, stage_id, rid, server_id)
        #  未加入赛季区服不加积分
        server_data = CrossSeasonServerRepository.get_by_server_id(server_id)
        if (not server_data) or (not server_data.server_status) or (server_data.joined_time > getCT()):
            self.is_return = False
            return
        # 未达到赛季限制等级不加段位经验
        limit_cfg = getProfile("TcActivityLimitCfg", ActivityType=ActivityType.CrossSeason)
        role_record = RoleRepository.get_by_rid(rid, "RoleLv")
        if role_record.role_lv < limit_cfg.RoleLvLimit:
            self.is_return = False
            return
        # 根据当前时间读取当前赛季角色记录
        with CAMutex(CrossSeasonLock.G_SEASON_ADD_SEASON_SCORE_LOCK.format(season_id=season_id, rid=rid)):
            role_data = CrossSeasonRoleRepository.get_by_seasonid_srvid_rid(season_id, rid, server_id)
            # 无记录时创建记录
            if not role_data:
                role_data = CrossSeasonRoleRepository.create(season_id, rid, get_server_id())
            # 添加赛季积分
            role_data.season_score += count
            # 更新赛季总积分榜单
            season_rank_utils.update_season_rank(rid, server_id, season_id, role_data.season_score)
            # 添加当前阶段积分
            stage_score = role_data.stage_score
            if stage_score.get(str(stage_id)):
                stage_score[str(stage_id)] += count
            else:
                stage_score[str(stage_id)] = count
            role_data.stage_score = stage_score
            # 更新赛季玩家阶段积分
            update_season_user_stage_score(season_id, stage_id, rid, server_id, stage_score[str(stage_id)])
            # 有分组时更新阶段排行榜单和分阶段每日榜单
            if group_id:
                season_rank_utils.update_season_group_rank(rid, server_id, season_id, stage_id, group_id,
                                                           stage_score[str(stage_id)])
                # 更新分赛区每日涨幅榜
                # day = get_day_of_season()
                # rank, score = season_rank_utils.get_season_group_increase_rank_score(rid, server_id, season_id,
                #                                                                      stage_id, group_id, day)
                # season_rank_utils.update_season_group_increase_rank(rid, server_id, season_id, stage_id, group_id,
                #                                                     day, score + count)
            CrossSeasonRoleRepository.save(role_data)

            if not activity_id:
                # 根据上下文的活动id记录积分来源
                activity_id = get_activity_id()
            if activity_id:
                season_score = CrossSeasonScoreRepository.get_by_rid_activityid(rid, activity_id)
                if not season_score:
                    season_score = CrossSeasonScoreRepository.create(rid, activity_id, season_id)
                season_score.season_score += count
                CrossSeasonScoreRepository.save(season_score)

        # 获得积分日志
        reserve = log_param.reserve
        reserve["ActivityId"] = activity_id
        log_param.reserve = reserve
        log_param.scene = str(get_action_id())
        CrossSeasonScoreLog.log_game(role_data.season_score, count, log_param)


class CrossSeasonDanExpGoods(object):
    """
    九州之巅段位经验物品
    在跨服使用时注意切换上下文
    kwargs 必传 增加数量count（int）
    """
    def add_award(self, rid, log_param, **kwargs):
        count = kwargs.get("count", 0) if kwargs.get("count", 0) else self.count
        server_id = get_server_id()
        season_id, stage_id, _ = get_season_base_info(need_award_time=False)
        # 没有赛季不加积分
        if not season_id:
            self.is_return = False
            return
        # 未加入赛季区服不加积分
        server_data = CrossSeasonServerRepository.get_by_server_id(server_id)
        if (not server_data) or (not server_data.server_status) or (server_data.joined_time > getCT()):
            self.is_return = False
            return
        # 未达到赛季限制等级不加段位经验
        limit_cfg = getProfile("TcActivityLimitCfg", ActivityType=ActivityType.CrossSeason)
        role_record = RoleRepository.get_by_rid(rid, "RoleLv")
        if role_record.role_lv < limit_cfg.RoleLvLimit:
            self.is_return = False
            return
        reserve = log_param.reserve
        with CAMutex(CrossSeasonLock.G_SEASON_ADD_SEASON_DAN_EXP_LOCK.format(season_id=season_id, rid=rid)):
            # 根据当前时间读取当前赛季角色记录
            role_data = CrossSeasonRoleRepository.get_by_seasonid_srvid_rid(season_id, rid, server_id)
            # 无记录时创建记录
            if not role_data:
                role_data = CrossSeasonRoleRepository.create(season_id, rid, server_id)
            # 记录旧段位
            reserve["OldLv"] = role_data.dan
            # 添加段位经验
            role_data.dan, role_data.dan_exp, push_list = self.add_dan_exp(rid, server_id, season_id,
                                                                           role_data.dan, role_data.dan_exp, count)
            CrossSeasonRoleRepository.save(role_data)
            # 推送消息到世界
            role_cache = ShareRoleInformation.get_role_information_from_cache_db(rid, server_id)
            for dan in push_list:
                send_system_msg(Channel.World, season_id, server_id, ext={"Dan": dan,
                                                                          "SmallHeadId": role_cache.small_head_id,
                                                                          "HeadFrameId": role_cache.head_frame_id,
                                                                          "NickName": role_cache.nick_name})

        # 记录段位经验日志
        reserve["NewLv"] = role_data.dan
        reserve["AddExp"] = count
        reserve["ActivityId"] = get_activity_id()
        log_param.reserve = reserve
        log_param.scene = str(get_action_id())
        CrossSeasonDanExpLog.log_game(role_data.dan, count, log_param)

    def add_dan_exp(self, rid, srv_id, season_id, dan, dan_exp, add_exp):
        """
        增加段位经验
        :param rid:
        :param srv_id:
        :param season_id:
        :param dan:
        :param dan_exp:
        :param add_exp:
        :return:
        """
        dan_exp += add_exp
        push_list = list()
        while True:
            next_dan_cfg = getProfile("TcCrossSeasonDan", DanId=dan+1)
            if next_dan_cfg and dan_exp >= next_dan_cfg.DanExp:
                dan += 1
                dan_exp -= next_dan_cfg.DanExp
                # 是否推送
                if next_dan_cfg.IsPush:
                    push_list.append(next_dan_cfg.DanId)
                # 首次达到某段位
                season_challenge_cache.unlock_one_dan_challenge(rid, srv_id, season_id, dan)
            else:
                break
        return dan, dan_exp, push_list
